using MedicalReportAssistant.Models;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MedicalReportAssistant.Services
{
    public class LocalKnowledgeBaseService : IKnowledgeBaseService
    {
        private readonly ILogger<LocalKnowledgeBaseService> _logger;
        private readonly string _dataPath;
        private readonly Dictionary<string, List<string>> _medicalTerms;
        private readonly List<CorrectionRule> _correctionRules;
        private readonly List<string> _reportTemplates;

        public LocalKnowledgeBaseService(ILogger<LocalKnowledgeBaseService> logger, IConfiguration configuration)
        {
            _logger = logger;
            _dataPath = configuration["KnowledgeBase:DataPath"] ?? "./Data";
            _medicalTerms = new Dictionary<string, List<string>>();
            _correctionRules = new List<CorrectionRule>();
            _reportTemplates = new List<string>();

            InitializeKnowledgeBase();
        }

        private void InitializeKnowledgeBase()
        {
            try
            {
                Directory.CreateDirectory(_dataPath);

                // 初始化医学术语库
                InitializeMedicalTerms();

                // 初始化纠错规则
                InitializeCorrectionRules();

                // 初始化报告模板
                InitializeReportTemplates();

                _logger.LogInformation("知识库初始化完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "知识库初始化失败");
            }
        }

        private void InitializeMedicalTerms()
        {
            var terms = new Dictionary<string, List<string>>
            {
                ["影像学检查"] = new List<string>
                {
                    "CT检查", "MRI检查", "X线检查", "超声检查", "核磁共振", "计算机断层扫描"
                },
                ["解剖部位"] = new List<string>
                {
                    "升结肠", "降结肠", "横结肠", "乙状结肠", "直肠", "肝右叶", "肝左叶", "胆囊", "胰腺", "脾脏", "双肾", "膀胱", "肺", "阴囊"
                },
                ["病变描述"] = new List<string>
                {
                    "结节灶", "密度影", "液气平面", "管壁增厚", "管腔变窄", "渗出改变", "淋巴结", "混杂密度灶", "低密度结节", "囊样低密度灶"
                },
                ["医学术语"] = new List<string>
                {
                    "术后复查", "对比", "同前", "未见异常", "未见扩张", "未见明显异常", "边界不清", "边界清晰"
                }
            };

            foreach (var category in terms)
            {
                _medicalTerms[category.Key] = category.Value;
            }
        }

        private void InitializeCorrectionRules()
        {
            _correctionRules.AddRange(new[]
            {
                new CorrectionRule
                {
                    Pattern = @"CA\b",
                    Replacement = "癌",
                    Reason = "医学术语规范化",
                    Type = CorrectionType.Terminology
                },
                new CorrectionRule
                {
                    Pattern = @"液气平\b",
                    Replacement = "液气平面",
                    Reason = "医学术语规范化",
                    Type = CorrectionType.Terminology
                },
                new CorrectionRule
                {
                    Pattern = @"稍高密度影\b",
                    Replacement = "稍高密度影像",
                    Reason = "医学术语规范化",
                    Type = CorrectionType.Terminology
                },
                new CorrectionRule
                {
                    Pattern = @"边界欠清晰",
                    Replacement = "边界不清",
                    Reason = "医学术语规范化",
                    Type = CorrectionType.Terminology
                },
                new CorrectionRule
                {
                    Pattern = @"大致同前",
                    Replacement = "较前无明显变化",
                    Reason = "医学术语规范化",
                    Type = CorrectionType.Terminology
                }
            });
        }

        private void InitializeReportTemplates()
        {
            _reportTemplates.AddRange(new[]
            {
                "临床诊断：{诊断}。\n影像所见：\n{影像描述}\n\n影像诊断：\n{诊断结论}",
                "检查部位：{部位}\n检查方法：{方法}\n\n影像表现：\n{表现}\n\n诊断意见：\n{意见}",
                "对比{对比时间}影像，现影像所见：\n{现影像描述}\n\n对比分析：\n{对比分析}"
            });
        }

        public async Task<List<string>> SearchMedicalTermsAsync(string query)
        {
            var results = new List<string>();
            
            foreach (var category in _medicalTerms)
            {
                var matches = category.Value.Where(term => 
                    term.Contains(query, StringComparison.OrdinalIgnoreCase) ||
                    query.Contains(term, StringComparison.OrdinalIgnoreCase)).ToList();
                
                results.AddRange(matches);
            }

            return await Task.FromResult(results.Distinct().ToList());
        }

        public async Task<List<string>> GetMedicalReportTemplatesAsync(string reportType)
        {
            return await Task.FromResult(_reportTemplates);
        }

        public async Task<List<CorrectionRule>> GetCorrectionRulesAsync()
        {
            return await Task.FromResult(_correctionRules);
        }

        public async Task AddMedicalTermAsync(string term, string category)
        {
            if (!_medicalTerms.ContainsKey(category))
            {
                _medicalTerms[category] = new List<string>();
            }

            if (!_medicalTerms[category].Contains(term))
            {
                _medicalTerms[category].Add(term);
                await SaveMedicalTermsAsync();
            }
        }

        public async Task AddCorrectionRuleAsync(CorrectionRule rule)
        {
            if (!_correctionRules.Any(r => r.Pattern == rule.Pattern))
            {
                _correctionRules.Add(rule);
                await SaveCorrectionRulesAsync();
            }
        }

        private async Task SaveMedicalTermsAsync()
        {
            try
            {
                var filePath = Path.Combine(_dataPath, "medical_terms.json");
                var json = JsonConvert.SerializeObject(_medicalTerms, Formatting.Indented);
                await File.WriteAllTextAsync(filePath, json);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存医学术语失败");
            }
        }

        private async Task SaveCorrectionRulesAsync()
        {
            try
            {
                var filePath = Path.Combine(_dataPath, "correction_rules.json");
                var json = JsonConvert.SerializeObject(_correctionRules, Formatting.Indented);
                await File.WriteAllTextAsync(filePath, json);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存纠错规则失败");
            }
        }

        public List<CorrectionItem> ApplyCorrectionRules(string text)
        {
            var corrections = new List<CorrectionItem>();

            foreach (var rule in _correctionRules)
            {
                if (Regex.IsMatch(text, rule.Pattern))
                {
                    var matches = Regex.Matches(text, rule.Pattern);
                    foreach (Match match in matches)
                    {
                        corrections.Add(new CorrectionItem
                        {
                            Original = match.Value,
                            Corrected = rule.Replacement,
                            Reason = rule.Reason,
                            Type = rule.Type
                        });
                    }
                }
            }

            return corrections;
        }
    }
} 